package sample.controller.article;

import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.UUID;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.apache.commons.io.IOUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.servlet.ModelAndView;

import sample.intf.article.dto.TArticle;
import sample.intf.article.dto.TArticlePicture;
import sample.intf.article.service.IArticleService;
import sample.intf.imagehelper.service.ExistingKeyFoundAction;
import sample.intf.imagehelper.service.GenerateImageInfoAction;
import sample.intf.imagehelper.service.IImageHelperService;
import sample.intf.imagehelper.service.TImageInfo;
import sample.intf.service.config.IConfigService;
import sample.intf.shared.BaseResponse;
import util.file.FileTypeHelper;

@Controller
@RequestMapping("/article")
public class ArticleController {

	@Autowired
	private IArticleService articleService;

	@Autowired
	private IImageHelperService imageHelper;

	@Autowired
	private IConfigService configService;

	@RequestMapping(value = "/list", method = RequestMethod.GET)
	public ModelAndView showArticleList() {
		ModelAndView mv = new ModelAndView("article/list");
		mv.addObject("list", articleService.selectAllArticles());
		return mv;
	}
	
	@RequestMapping(value = "/show/{id}", method = RequestMethod.GET)
	public ModelAndView showArticleDetail(@PathVariable long id) {
		TArticle article = articleService.selectArticle(id);
		ModelAndView mv = new ModelAndView("article/show");
		if (article == null)
			return mv;
		mv.addObject("article", article);
		return mv;
	}

	@RequestMapping(value = "/get/{id}", method = RequestMethod.POST)
	public @ResponseBody BaseResponse getArticleDetail(@PathVariable long id) {
		TArticle article = articleService.selectArticle(id);
		BaseResponse response = new BaseResponse();
		if (article == null)
			response.setCode(1);
		else
			response.setObj(article);
		return response;
	}

	@RequestMapping(value = "/picture/{fileName}.{fileExt}", method = RequestMethod.GET)
	public void showArticlePicture(@PathVariable String fileName, @PathVariable String fileExt,
			HttpServletRequest request, HttpServletResponse response) throws IOException {
		String pictureRootPath = configService.getArticlePictureRootPath(request);

		// 删除危险的字符
		fileName = fileName + "." + fileExt;
		fileName = fileName.replace("/", "");
		fileName = fileName.replace("\\", "");

		// 检查照片是否存在
		File pictureFile = new File(pictureRootPath, fileName);
		if (!pictureFile.exists()) {
			response.sendError(404);
			return;
		}

		// 发送图片
		response.setContentType("image/jpeg");
		try (FileInputStream in = new FileInputStream(pictureFile)) {
			IOUtils.copy(in, response.getOutputStream());
		}
	}

	@RequestMapping(value = "/add", method = RequestMethod.GET)
	public ModelAndView showAddArticle() {
		return new ModelAndView("article/add");
	}

	@RequestMapping(value = "/add", method = RequestMethod.POST)
	public @ResponseBody BaseResponse addArticle(final HttpServletRequest request, @RequestBody TArticle article) throws Exception {
		BaseResponse response = new BaseResponse();
		final Map<TArticlePicture, byte[]> pictures = new HashMap<>();
		String content = imageHelper.transform(article.getContent(), null, new GenerateImageInfoAction() {
			@Override
			public TImageInfo generate(String originalFileName, String imageType, byte[] imageData) throws Exception {
				String fileExt = FileTypeHelper.translateTypeToExt(imageType);
				if (fileExt == null)
					return null;
				// 记录图片信息
				TArticlePicture picture = new TArticlePicture();
				picture.setGuid(UUID.randomUUID().toString());
				picture.setKey(""); // unused
				picture.setPath(picture.getGuid() + "." + fileExt);
				pictures.put(picture, imageData);
				// 设置图片
				TImageInfo info = new TImageInfo();
				info.setKey(picture.getGuid());
				info.setSrc(request.getContextPath() + "/article/picture/" + picture.getPath());
				return info;
			}
		});
		article.setContent(content);
		articleService.insertArticle(article);
		for (Entry<TArticlePicture, byte[]> picture : pictures.entrySet()) {
			picture.getKey().setArticleId(article.getId());
			articleService.saveArticlePicture(picture.getKey(), configService.getArticlePictureRootPath(request),
					picture.getValue(), true);
		}
		response.setObj(article.getId());
		return response;
	}

	@RequestMapping(value = "/delete", method = RequestMethod.POST)
	public @ResponseBody BaseResponse deleteArticle(@RequestBody TArticle article, HttpServletRequest request) {
		BaseResponse response = new BaseResponse();
		String pictureRootPath = configService.getArticlePictureRootPath(request);
		articleService.deleteArticle(article.getId());
		articleService.deleteArticlePictures(article.getId(), pictureRootPath);
		return response;
	}
	
	@RequestMapping(value = "/modify/{id}", method = RequestMethod.GET)
	public ModelAndView showModifyArticle(@PathVariable long id) {
		TArticle article = articleService.selectArticle(id);
		if (article == null)
			return new ModelAndView("redirect:/article/list");
		ModelAndView mv = new ModelAndView("article/modify");
		mv.addObject("article", article);
		return mv;
	}

	@RequestMapping(value = "/modify/{id}", method = RequestMethod.POST)
	public @ResponseBody BaseResponse modifyArticle(@PathVariable long id, @RequestBody TArticle article,
			final HttpServletRequest request) throws Exception {
		BaseResponse response = new BaseResponse();
		String pictureRootPath = configService.getArticlePictureRootPath(request);
		// 请求处理
		final Map<TArticlePicture, byte[]> pictures = new HashMap<>();
		final ArrayList<String> existingKeys = new ArrayList<String>();
		String content = imageHelper.transform(article.getContent(), new ExistingKeyFoundAction() {
			@Override
			public boolean check(String key) throws Exception {
				// 在这里进行对key格式的检查
				existingKeys.add(key);
				return true;
			}
		}, new GenerateImageInfoAction() {
			@Override
			public TImageInfo generate(String originalFileName, String imageType, byte[] imageData) throws Exception {
				String fileExt = FileTypeHelper.translateTypeToExt(imageType);
				if (fileExt == null)
					return null;
				// 记录图片信息
				TArticlePicture picture = new TArticlePicture();
				picture.setGuid(UUID.randomUUID().toString());
				picture.setKey(""); // unused
				picture.setPath(picture.getGuid() + "." + fileExt);
				pictures.put(picture, imageData);
				// 设置图片
				TImageInfo info = new TImageInfo();
				info.setKey(picture.getGuid());
				info.setSrc(request.getContextPath() + "/article/picture/" + picture.getPath());
				return info;
			}
		});
		// 准备TArticle对象
		article.setId(id);
		article.setContent(content);
		// 更新Article
		if (!articleService.updateArticle(article)) {
			response.setCode(1);
			return response;
		}
		// 获取被用户删掉得图片
		List<TArticlePicture> missingPictures = articleService.selectMissingArticlePictures(id, existingKeys);
		// 删除这些图片
		articleService.deleteArticlePictures(missingPictures, pictureRootPath);
		// 保存新增加的图片
		for (Entry<TArticlePicture, byte[]> picture : pictures.entrySet()) {
			picture.getKey().setArticleId(article.getId());
			articleService.saveArticlePicture(picture.getKey(), configService.getArticlePictureRootPath(request),
					picture.getValue(), true);
		}
		response.setObj(article.getId());
		return response;
	}
}
